/*
 * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package jsr203.nio.file.attribute;

import java.io.IOException;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import jsr203.nio.file.FileRef;
import jsr203.nio.file.Path;

/**
 * A file attribute view that provides a view of the file attributes commonly
 * associated with files on file systems used by operating systems that implement
 * the Portable Operating System Interface (POSIX) family of standards.
 *
 * <p> Operating systems that implement the <a href="http://www.opengroup.org">
 * POSIX</a> family of standards commonly use file systems that have a
 * file <em>owner</em>, <em>group-owner</em>, and related <em>access
 * permissions</em>. This file attribute view provides read and write access
 * to these attributes.
 *
 * <p> The {@link #readAttributes() readAttributes} method is used to read the
 * file's attributes. The file {@link PosixFileAttributes#owner() owner} is
 * represented by a {@link UserPrincipal} that is the identity of the file owner
 * for the purposes of access control. The {@link PosixFileAttributes#group()
 * group-owner}, also represented by a <tt>UserPrincipal</tt>, is the
 * identity of the group owner. The exact definition of group is implementation
 * specific but typically it represents an identity created for administrative
 * purposes so as to determine the access rights for the members of the group.
 *
 * <p> The {@link PosixFileAttributes#permissions() permissions} attribute is a
 * set of access permissions. This file attribute view provides access to the nine
 * permission defined by the {@link PosixFilePermission} class.
 * These nine permission bits determine the <em>read</em>, <em>write</em>, and
 * <em>execute</em> access for the file owner, group, and others (others
 * meaning identities other than the owner and members of the group). Some
 * operating systems and file systems may provide additional permission bits
 * but access to these other bits is not defined by this class in this release.
 *
 * <p> This interface extends {@link UserPrincipalLookupService} to allow for
 * the lookup of user or group names.
 *
 * <p> <b>Usage Example:</b>
 * Suppose we need to print out the owner and access permissions of a file:
 * <pre>
 *     FileRef file = ...
 *     PosixFileAttributes attrs = file.newFileAttributeView(PosixFileAttributeView.class, true)
 *         .readAttributes();
 *     System.out.format("%s %s%n",
 *         atts.owner().getName(),
 *         PosixFilePermission.toString(attrs.permissions()));
 *
 * </pre>
 * Furthermore, suppose we need to create a new file <tt>"db"</tt> for which
 * the owner should have complete access, the group should have read access,
 * and others should not have any access.
 *
 * <pre>
 *     Path path = ...
 *     PosixFileAttributeView view = path.getFileSystem()
 *         .newFileAttributeView(PosixFileAttributeView.class);
 *     Attribute&lt;Set&lt;PosixFilePermission&gt;&gt; perms = view.newPermissionsAttribute()
 *         .setValue(EnumSet.of(OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ));
 *     path.createFile(perms);
 * </pre>
 *
 * @since 1.7
 *
 * @see Attributes#readPosixFileAttributes
 */

public interface PosixFileAttributeView
    extends BasicFileAttributeView, UserPrincipalLookupService
{
    @Override
    PosixFileAttributeView bind(FileRef file);

    @Override
    PosixFileAttributeView bind(FileRef file, boolean followLinks);

    /**
     * @throws  UnsupportedOperationException
     *          If not following links, the file is a link, and the implementation
     *          does not support reading the attributes of a symbolic link
     * @throws  IllegalStateException      {@inheritDoc}
     * @throws  IOException                {@inheritDoc}
     * @throws  SecurityException
     *          In the case of the default provider, a security manager is
     *          installed, and it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
     *          or its {@link SecurityManager#checkRead(String) checkRead} method
     *          denies read access to the file.
     */
    @Override
    PosixFileAttributes readAttributes() throws IOException;

    /**
     * Constructs an {@link Attribute} object to represent the value of a
     * {@link PosixFileAttributes#permissions permissions} attribute.
     *
     * <p> The resulting object can be used with methods such as {@link
     * Path#createFile createFile} or {@link Path#createDirectory createDirectory}
     * to set the initial permissions when creating a file or directory.
     *
     * <p> When the access permissions are set at file creation time then the actual
     * value of the permissions may differ that the value of the attribute object.
     * The reasons for this are implementation specific. On UNIX systems, for
     * example, a process has a <em>umask</em> that impacts the permission bits
     * of newly created files. Where an implementation supports the setting of
     * the access permissions, and the underlying file system supports access
     * permissions, then it is required that the value of the actual access
     * permissions will be equal or less than the value of the attribute
     * provided to the {@link jsr203.nio.file.Path#createFile createFile} or
     * {@link jsr203.nio.file.Path#createDirectory createDirectory} methods. In
     * other words, the file may be more secure than requested.
     *
     * @return  A new attribute object; its initial value is an empty set
     *
     * @throws  UnsupportedOperationException
     *          If the file system does not support creating a file or directory
     *          with initial access permissions that are set atomically when the
     *          file or directory is created
     */
    Attribute<Set<PosixFilePermission>> newPermissionsAttribute();

    /**
     * @throws  UnsupportedOperationException           {@inheritDoc}
     * @throws  IllegalStateException                   {@inheritDoc}
     * @throws  IOException                             {@inheritDoc}
     * @throws  SecurityException                       {@inheritDoc}
     */
    @Override
    PosixFileAttributeView setTimes(Long lastModifiedTime,
                                    Long lastAccessTime,
                                    Long createTime,
                                    TimeUnit unit) throws IOException;

    /**
     * Updates the file permissions.
     *
     * @param   perms
     *          The new set of permissions
     *
     * @return  this attribute view
     *
     * @throws  UnsupportedOperationException
     *          If not following links, the file is a link, and the implementation
     *          does not support updating the permissions of a symbolic link
     * @throws  ClassCastException
     *          If the sets contains elements that are not of type {@code
     *          PosixFilePermission}
     * @throws  IllegalStateException
     *          If the attribute view is not bound, or if bound to an object
     *          that is not open for writing
     * @throws  IOException
     *          If an I/O error occurs
     * @throws  SecurityException
     *          In the case of the default provider, a security manager is
     *          installed, and it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
     *          or its {@link SecurityManager#checkWrite(String) checkWrite}
     *          method denies write access to the file.
     */
    PosixFileAttributeView setPermissions(Set<PosixFilePermission> perms)
        throws IOException;

    /**
     * Updates the file owner.
     *
     * <p> The {@code owner} parameter is a {@link UserPrincipal} representing
     * the owner. Its {@link UserPrincipal#isGroup() isGroup()} method returns
     * <tt>false</tt>.
     *
     * @param   owner
     *          The new file owner
     *
     * @return  this attribute view
     *
     * @throws  UnsupportedOperationException
     *          If not following links, the file is a link, and the implementation
     *          does not support updating the owner of a symbolic link
     * @throws  IllegalArgumentException
     *          If the pre-conditions for the {@code owner} parameter is not met
     * @throws  IllegalStateException
     *          If the attribute view is not bound, or if bound to an object
     *          that is not open for writing
     * @throws  IOException
     *          If an I/O error occurs
     * @throws  SecurityException
     *          In the case of the default provider, and a security manager is
     *          installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
     *          or its {@link SecurityManager#checkWrite(String) checkWrite}
     *          method denies write access to the file.
     */
    PosixFileAttributeView setOwner(UserPrincipal owner) throws IOException;

    /**
     * Updates the file group-owner.
     *
     * <p> The {@code group} parameter is a {@link UserPrincipal} representing
     * the group. Its {@link UserPrincipal#isGroup() isGroup()} method returns
     * {@code true}.
     *
     * @param   group
     *          The new file group-owner
     *
     * @return  this attribute view
     *
     * @throws  UnsupportedOperationException
     *          If not following links, the file is a link, and the implementation
     *          does not support updating the group-owner of a symbolic link
     * @throws  IllegalArgumentException
     *          If the pre-conditions for the {@code group} parameter is not met
     * @throws  IllegalStateException
     *          If the attribute view is not bound, or if bound to an object
     *          that is not open for writing
     * @throws  IOException
     *          If an I/O error occurs
     * @throws  SecurityException
     *          In the case of the default provider, and a security manager is
     *          installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
     *          or its {@link SecurityManager#checkWrite(String) checkWrite}
     *          method denies write access to the file.
     */
    PosixFileAttributeView setGroup(UserPrincipal group)
        throws IOException;
}
